//: A UIKit based Playground for presenting user interface

//1. 引入
import UIKit

//2. 标记
var vari = "Hello World"

//3. 注释
var a = 1+0;

//4. 分号
var al = 12;var a2 = 12;
var a3 = 13
var a4 = 19;
//5. 标识符
//6. 关键字
//7. 空格
//8. 字面量
//9. 打印输出

//可选类型

//强制解析
var optionalInteger: Int?
optionalInteger = 0
if optionalInteger != nil{
    print(optionalInteger!)
}else{
    print("optionalInteger is nil")
}

//自动解析
var mString: String!
if mString != nil{
    print(mString)
}else{
    print("mString is nil")
}

//可选绑定
var myString: String?
myString = "hello"
if let yourString = myString{
    print(yourString)
}else{
    print("yourString is nil")
}

//常量
//常量声明
let constantString = "1"

//类型标注
let constantInt: Int = 1

//常量命名
let 你好 = "你好"
print(你好)
let 😀 = "露齿标准的笑"
print(😀)

//常量输出
let name = "Hell"
let hello = "haha"
print("\(name)  \(hello)")

//闭区间运算符
for index in 1...5{
    print(index)
}

//半开区间运算符
for index in 1..<5{
    print(index)
}

//switch fallthrough
var index = 10
switch index{
case 20:
    print("值为20")
case 10,15:
    print("值为10或15")
    fallthrough
case 5:
    print("值为5")
default:
    print("默认值")
}

//字符串插入值
var insetA = "我"
var insertB = "insert2"
print("\(insetA)\(insertB)")
//字符串长度
insertB.count
//unicode字符串
for code in insetA.utf8{
    print("\(code)")
}

//字符串连接字符
var stringA = "Hello,"
var charA: Character = "A"
stringA.append(charA)
print(stringA)

//创建数组
var arrA = [Int](repeating: 1, count: 5)
var arrB = [Int]()
var arrC: [Int] = [1,2,3]
//访问数组
arrA.count
//修改数组
arrA[0] = 9
arrA[0]
//遍历数组1.for-in
for item in arrA{
    print(item)
}
//遍历数组2.for-in,同时遍历索引
for (index,item) in arrA.enumerated(){
    print("第\(index)位置的值：\(item)")
}
//合并数组
var arrD = arrA+arrC
for item in arrD{
    print("合并后：\(item)")
}
//count属性
print("数组D的长度：\(arrD.count)")
//isEmpty属性
print("数组为空？：\(arrD.isEmpty)")
print("数组为空？：\(arrB.isEmpty)")


//创建字典
var dicA = [Int:String]()
print("dicA isEmpty?\(dicA.isEmpty)")

var dicB: [Int:String] = [1:"a",2:"b"]
//访问字典
print(dicB[1]!)
//修改字典
dicB.updateValue("new a", forKey: 1)
print(dicB[1]!)
dicB[1]="new A"
print(dicB[1]!)
//移除key-value
dicB.removeValue(forKey: 2)
//print(dicB[2]==nil)
//遍历字典
for (key,value) in dicB {
    print("dicB\(key)=\(value)")
}
//字典转为数组
let key = [Int](dicB.keys)
let value = [String](dicB.values)
for item in key{
    print(item)
}
//count属性
print(dicB.count)
print(dicB.isEmpty)

//函数定义
func sum(a: Int,b: Int)->Int{
    return a+b
}
//函数调用
print(sum(a: 2, b: 1))
//元组作为返回值
func minMax(array: [Int]) -> (min: Int,max: Int){
    var currentMin = array[0]
    var currentMax = array[1]
    for item in array[1..<array.count]{
        if item < currentMin{
            currentMin = item
        }else if item > currentMax{
            currentMax = item
        }
    }
    return (currentMin,currentMax)
}
let arrayC: [Int]=[1,2,3,4,5,3452,333,666,-111]
print(minMax(array: arrayC))
//函数参数名称
//1.局部参数名 只能在函数内使用
func sample(num: Int){
    print(num)
}
//2.外部参数名 在调用函数时使用
func sample1(firstArg a: Int,lastArg b: Int){
    print(a+b)
}
sample1(firstArg: 1, lastArg: 1)

//可变参数函数
func variArgs<N>(members:N...){
    for item in members{
        print(item)
    }
}
variArgs(members: 1,2,3)
variArgs(members: 1.1,2.2,3.2)
variArgs(members: "aa","bb")
//常量，变量，I/O参数
var x = 1
var y = 2
func swapTwoInts(_ a: inout Int,_ b: inout Int){
    let tempA = a
    a = b
    b = tempA
}
swapTwoInts(&x, &y)
print("调用函数后x=\(x),y=\(y)")
//使用函数类型,函数也是一种类型
var addition:(Int,Int)->Int = sum(a:b:)
print(addition(12,21))
//函数作为参数类型，返回类型
func another(addition:(Int,Int)->Int,a: Int,b: Int){
    print(addition(a,b))
}
another(addition: addition, a: 12, b: 12)

//函数嵌套：函数内定义新的函数，外层函数可以调用内层函数
func outer(forDecrement a: Int) ->()-> Int{
    var ini = 0
    func decrement() -> Int{
        ini -= a
        return ini
    }
    return decrement
}

let inner = outer(forDecrement: 21)
inner()

//闭包
let printHello = {print("Hello World")}
printHello()
//闭包表达式
//sorted方法
let arr = ["ab","ac","bc","ba"]
func compare(a: String ,b: String)->Bool{
    return a<b;
}
let arrNew = arr.sorted(by: compare)
//参数与名称缩写
let reverse = arr.sorted(by: {$0 > $1})
print(reverse)
//运算符函数
print(arr.sorted(by: >))
//尾随闭包
print(arr.sorted{$0 > $1})
//捕获值：闭包可以捕获常量或者变量，即使这些量的原域已不存在
func runningTotal(forIncrement amount: Int) -> ()-> Int{
    var total = 0;
    func inrementor()->Int{
        print(total)
        total += amount
        print(total)
        //赋值之后保存了total的副本
        return total
    }
    return inrementor
}
let increment = runningTotal(forIncrement: 10)
increment()
increment()


//枚举
enum Week{
    case Mon
    case Tues
    case Wedens
    case Thurs
    case Fri
    case Satur
    case Sun
}
//相关值
enum Student{
    case Name(String)
    case Mark(Int,Int,Int)
}
let stud = Student.Name("Run")
let stuM = Student.Mark(12, 12, 12)
switch stuM {
    case Student.Name(let studName):
        print("\(studName)")
    case Student.Mark(let m1,let m2,let m3):
        print("\(m1) \(m2) \(m3)")
}
//原始值


//结构体
struct Teacher{
    var name: String
    var age: Int
    var sex: String
    var des: String
    
    init(name: String,age: Int,sex: String,des: String) {
        self.name = name
        self.age = age
        self.sex = sex
        self.des = des
    }
}
let xiaoli = Teacher(name: "Mrs Zhou", age: 26, sex: "female", des: "no no no")
print(xiaoli.name)
print(xiaoli.age)
print(xiaoli.sex)
print(xiaoli.des)

//类的定义
class people{
    var name: String
    var age: Int
    var height: Double
    var weight: Double
    init(name: String,age: Int,height: Double,weight: Double) {
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    }
}
//类允许继承

let zhangsan = people(name:"zhangsan",age:12,height:120,weight:40)
print(zhangsan.name)

//Swift属性
//1.存储属性
//2.计算属性

//变量存储属性：允许修改
//常量存储属性：初始化后不允许修改
//延迟存储属性：当第一次被调用时才会计算其初始值的属性

//计算属性：不直接存储值
class cal{
    var no1 = 0.0,no2 = 0.0
    var length = 300.0,breadth = 150.0
    
    var middle:(Double,Double){
        get{
            return (length/2,breadth/2)
        }
        set{
            no1 = newValue.0 - length/2
            no2 = newValue.1 - breadth/2
        }
    }
}
var result = cal()
print(result.middle)
result.middle = (0.0,10.0)
print(result.no1)
print(result.no2)
//只读计算属性：只有getter没有setter的计算属性

//属性观察器：监控和响应属性值的变化
class PropertyListener {
    var age: Int = 0{
        willSet(newValue){
            print("修改前旧值：\(age)新值：\(newValue)")
        }
        didSet{
            print("修改完成新值:\(age)")
        }
    }
}

var proper = PropertyListener()
proper.age = 10
proper.age = 110

//继承
class supperClass{
    var cons:Int;
    init(a: Int) {
        self.cons = a
    }
}
class subClass: supperClass {
    
}
//防止重写
final class supperForbiClass{
    
}


class Person{
    var name: String?
    
    init(name: String) {
        self.name = name
        print("初始化完成")
    }
    
    deinit {
        print("析构完成")
    }
}

var person1: Person?
var person2: Person?
var person3: Person?

person1 = Person(name: "lisi")
person2 = person1
person3 = person1

person1 = nil
person2 = nil
person3 = nil

//自动引用计数
//弱引用
class Module {
    let name: String
    init(name: String) { self.name = name }
    var sub: SubModule?
    deinit { print("\(name) 主模块") }
}

class SubModule {
    let number: Int
    
    init(number: Int) { self.number = number }
    
    weak var topic: Module?
    
    deinit { print("子模块 topic 数为 \(number)") }
}

var toc: Module?
var list: SubModule?
toc = Module(name: "ARC")
list = SubModule(number: 4)
toc!.sub = list
list!.topic = toc

toc = nil
list = nil

//闭包引起的y循环引用
class HtmlElement{
    let name: String
    let text: String?
    init(name: String,text: String? = nil) {
        self.name = name
        self.text = text
    }
    
    lazy var asHtml: ()->String = {
        [unowned self] in
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        }else{
            return "<\(self.name)>"
        }
    }
    
    deinit {
        print("\(name)is being deinited")
    }
}

var h1: HtmlElement? = HtmlElement(name: "h1",text: "这是一级标题")
print(h1!.asHtml())

h1 = nil

//类型转换

//扩展
extension Int{
    var add: Int{return self+100}
    var del: Int{return self - 100}
    var mul: Int{
        return self*100
    }
    var div: Int{return self/100}
}

1.add

//协议
protocol class1{
    var status: Int{get set}
    var message: String{get set}
    func onSuccess()->String
    func onFailure()->String
}
class Request: class1 {
    var status: Int
    
    var message: String
    func onSuccess() -> String {
        message = "success"
        return "success"
    }
    func onFailure() -> String {
        message = "failure"
        return "failure"
    }
    init(message: String,status: Int) {
        self.message = message
        self.status = status
    }
}
var re1 = Request(message: "请求",status: 12)
print(re1.onSuccess())

struct City{
    var value: Int = -1
}

var acc = City()
var b = acc
acc.value = 0
print("\(acc.value)  \(b.value)")
